home *** CD-ROM | disk | FTP | other *** search
- char *ckzv = "OS-9 file support, 5A(08) 01 Dec 92";
- char *ckzsys = " OS-9/68000";
-
- /* c k 9 F I O -- Kermit file system support for OS-9/68k systems */
-
- /*
- Author: Peter Scholz,
- Ruhr University Bochum, Department for Analytical Chemistry,
- Federal Republic of Germany, February 1987
-
- 04/30/87 Robert Larson Cleanup, merge with standard C-kermit
- 04/07/89 Robert Larson Update for ckermit 4f(77)
- 07/16/89 Robert Larson 4f(85)
- Edition: 5A(01)
- 06/21/91 Chris Hemsing general adaption to 5A(171)
- miscellaneous bug fixes, utilization of
- initial file size.
- 07/25/91 Chris Hemsing minor bug fixes, changes for gnu (ansi) C
- 01/14/92 Chris Hemsing uct/localtime bug fix
- 05/26/92 Chris Hemsing zltor and zrtol bug fix
- Edition: 5A(05)
- 06/30/92 Chris Hemsing pipeopen stderr bug fix,dir shows filesize
- Edition: 5A(06)
- 07/09/92 Chris Hemsing removed all chaining which would save a
- process but f$chain does not look in PATH
- Edition: 5A(07)
- 07/10/92 Chris Hemsing remove whole process tree of a lower fork
- Edition: 5A(08)
- 12/01/92 Chris Hemsing zgtdir bugs repaired: upmost dir not closed
- closedir of non-open dir could be called
- adapted from Unix C-Kermit
- Author: Frank da Cruz (SY.FDC@CU20B),
- Columbia University Center for Computing Activities, January 1985.
- Copyright (C) 1985, 1992, Trustees of Columbia University in the City of New
- York. Permission is granted to any individual or institution to use this
- software as long as it is not sold for profit. This copyright notice must be
- retained. This software may not be included in commercial products without
- written permission of Columbia University.
- */
- /* Includes */
-
- #include "ckcdeb.h" /* Typedefs, debug formats, etc */
- #include "ckcker.h" /* Kermit definitions */
- #include <dir.h> /* Directory structure */
- #include <direct.h>
- #include <modes.h>
- #include <procid.h>
- #include <signal.h>
- #include <strings.h>
- #include <time.h>
-
- /* Definitions of some system commands */
-
- char *DIRCMD = "dir -e "; /* For directory listing with filename*/
- char *DIRCM2 = "dir -e "; /* For directory listing without filename*/
- char *DELCMD = "del "; /* For file deletion */
- char *TYPCMD = "list "; /* For typing a file */
- char *PWDCMD = "pd "; /* For saying where I am */
-
- char *SPACMD = "free ";
- char *SPACM2 = "free "; /* For space in specified directory */
-
- char *WHOCMD = "procs -e "; /* we have no who yet*/
-
- /*
- Functions (n is one of the predefined file numbers from ckermi.h):
-
- zopeni(n,name) -- Opens an existing file for input.
- zopeno(n,name,attr,fcb) -- Opens a new file for output.
- zclose(n) -- Closes a file.
- zchin(n,&c) -- Gets the next character from an input file.
- zsout(n,s) -- Write a null-terminated string to output file,buffered.
- zsoutl(n,s) -- Like zsout, but appends a line terminator.
- zsoutx(n,s,x) -- Write x characters to output file, unbuffered.
- zchout(n,c) -- Add a character to an output file, unbuffered.
- zchki(name) -- Check if named file exists and is readable,return size.
- zchko(name) -- Check if named file can be created.
- zchkspa(name,n) -- Check if n bytes available to create new file, name.
- znewn(name,s) -- Make a new unique file name based on the given name.
- zdelet(name) -- Delete the named file.
- zxpand(string) -- Expands the given wildcard string into a list of files.
- znext(string) -- Returns the next file from the list in "string".
- zxcmd(cmd) -- Execute the command in a lower fork.
- zclosf() -- Close input file associated with zxcmd()'s lower fork.
- zrtol(n1,n2) -- Convert remote filename into local form.
- zltor(n1,n2) -- Convert local filename into remote form.
- zchdir(dirnam) -- Change working directory.
- zhome() -- Return pointer to home directory name string.
- zkself() -- Kill self, log out own job.
- zsattr(struc zattr *) -- Return attributes for file which is being sent.
- */
-
-
- /* Some systems define these in include files, others don't... */
-
- #define MAXWLD 500
-
- /* Declarations */
- #define MAXPATH 256 /* not really an OS-9 restriction */
-
-
- FILE *fp[ZNFILS] = { /* File pointers */
- NULL, NULL, NULL, NULL, NULL, NULL, NULL };
-
- /* (PWP) external def. of things used in buffered file input and output */
- #ifdef DYNAMIC
- extern CHAR *zinbuffer, *zoutbuffer;
- #else
- extern CHAR zinbuffer[], zoutbuffer[];
- #endif /* DYNAMIC */
- extern CHAR *zinptr, *zoutptr;
- extern int zincnt, zoutcnt;
-
- struct fildes cur_in_fd; /* current input filedesc */
- static int cur_in_size = -1; /* current input file length */
-
- static int pipe_pid; /* pid of child fork */
- static int fcount; /* Number of files in wild group */
- char *malloc(), *getenv(), *strcpy(); /* System functions */
- extern errno; /* System error code */
-
- char *mtchs[MAXWLD], /* Matches found for filename */
- **mtchptr; /* Pointer to current match */
-
- /* Z K S E L F -- Kill Self: log out own job, if possible. */
-
- zkself() { /* For "bye" */
- procid pbuf;
- _get_process_desc(getpid(),sizeof(pbuf),&pbuf);
- if (kill((int)pbuf._pid,SIGKILL)==0)
- doexit(GOOD_EXIT,-1);/*kill parent process*/
- else
- doexit(errno,-1);
- }
-
- char *zgtdir() {
- /* I'm sure this can be done better... */
- static char cwd[MAXPATH];
- char backpath[MAXPATH];
- char *bpp = backpath, *path = cwd;
- DIR *dirp;
- struct direct *dp;
- long inode, inode2;
- char dots[MAXPATH];
-
- if((dirp = opendir(".")) == NULL) return NULL;
- if((readdir(dirp) == NULL) || (dp = readdir(dirp)) == NULL) {
- closedir(dirp);
- return (char *)NULL;
- }
- inode = dp->d_addr;
- *path++ = '/';
- _gs_devn(dirp->dd_fd, path);
- path += strlen(path);
- closedir(dirp);
- strcpy(dots, "..");
- for(;;) {
- if((dirp = opendir(dots)) == NULL) return NULL;
- if((readdir(dirp) == NULL) || (dp = readdir(dirp)) == NULL) {
- closedir(dirp);
- return (char *)NULL;
- }
- inode2 = dp->d_addr;
- if(inode == inode2) break; /* .. and . are same, we are done */
- do {
- if((dp = readdir(dirp)) == NULL) {
- closedir(dirp);
- return (char *)NULL;
- }
- } while(dp->d_addr != inode);
- *bpp++ = '/';
- strcpy(bpp, dp->d_name);
- bpp += strlen(bpp);
- closedir(dirp);
- inode = inode2;
- strcat(dots, "/..");
- }
- closedir(dirp); /* close upmost directory */
- while(bpp > backpath) {
- *bpp = '\0';
- while(*--bpp != '/') {}
- strcpy(path, bpp);
- path += strlen(path);
- }
- return cwd;
- }
-
-
- /* Z O P E N I -- Open an existing file for input. */
-
- zopeni(n,name) int n; char *name; {
- debug(F111," zopeni",name,n);
- debug(F101," fp","",(int) fp[n]);
- if (chkfn(n) != 0) return(0);
- zincnt = 0; /* Reset input buffer */
- if (n == ZSYSFN) { /* Input from a system function? */
- /*** Note, this function should not be called with ZSYSFN ***/
- /*** Always call zxcmd() directly, and give it the real file number ***/
- /*** you want to use. ***/
- debug(F110,"zopeni called with ZSYSFN, failing!",name,0);
- return(0); /* fail. */
- }
- if (n == ZSTDIO) { /* Standard input? */
- if (isatty(0)) {
- ermsg("Terminal input not allowed");
- debug(F110,"zopeni: attempts input from unredirected stdin","",0);
- return(0);
- }
- fp[ZIFILE] = stdin;
- return(1);
- }
- fp[n] = fopen(name,"r"); /* Real file. */
- debug(F111," zopeni", name, (int) fp[n]);
- if (fp[n] == NULL) perror("zopeni");
- return((fp[n] != NULL) ? 1 : 0);
- }
-
- /* Z O P E N O -- Open a new file for output. */
-
- zopeno(n,name,zz,fcb)
- /* zopeno */ int n; char *name; struct zattr *zz; struct filinfo *fcb; {
-
- /* As of Version 5A, the attribute structure and the file information */
- /* structure are included in the arglist. */
-
- char *p;
- int pn;
- debug(F111,"zopeno",name,n);
- if (chkfn(n) != 0) return(0);
- zoutcnt = 0;
- zoutptr = zoutbuffer;
- if (fcb)
- {
- debug(F101,"zopeno fcb disp","",fcb->dsp);
- debug(F101,"zopeno fcb type","",fcb->typ);
- debug(F101,"zopeno fcb char","",fcb->cs);
- }
- else debug(F100,"zopeno fcb is NULL","",0);
- if ((n == ZCTERM) || (n == ZSTDIO))
- { /* Terminal or standard output */
- fp[ZOFILE] = stdout;
- debug(F101," fp[]=stdout", "", (int) fp[n]);
- return(1);
- }
-
- /* A real file. Open it in desired mode (create or append). */
- p = "w"; /* Assume write/create mode */
- if (fcb) { /* If called with an FCB... */
- if (fcb->dsp == XYFZ_A) /* Does it say Append? */
- p = "a"; /* Yes. */
- }
- if (access(name,0) == 0) /* does file exist ? */
- {
- if ((fp[n] = fopen(name,p)) == NULL) /* Simply open the file */
- {
- perror("zopeno can't open");
- return(0);
- }
- debug(F111, " exist:fp[n]",p, (int) fp[n]);
- }
- else /* file does not exist, we can open with initial size */
- /* this is very important for long files not to be too fragmented */
- /* so that after a long transmission OS-9 may finish saying that */
- /* the segment allocation table is full */
- {
- if ((zz) && ((zz->length > 0) || (zz->lengthk > 0)))
- /* length estimate available ? */
- {
- if ((pn = create(name,S_IREAD+S_IWRITE+S_ISIZE,
- S_IREAD+S_IWRITE,
- (zz->length > 0) ? zz->length : (zz->lengthk*1024L))) != -1)
- {
- debug(F111, " create with init. size:",p,
- (zz->length > 0) ? zz->length : (zz->lengthk*1024L));
- if ((fp[n] = fdopen(pn,"w")) == NULL) /* get filepntr for pn */
- {
- perror("zopeno can't open");
- return(0);
- }
- debug(F111, " create with init. size:fp[n]",p, (int) fp[n]);
- }
- else
- {
- perror("zopeno can't open");
- return(0);
- }
- }
- else /* no length available */
- {
- if ((fp[n] = fopen(name,p)) == NULL) /* Simply open the file */
- {
- perror("zopeno can't open");
- return(0);
- }
- debug(F111, " create without init size fp[n]",p, (int) fp[n]);
- }
- }
- if((zz) && (zz->systemid.val[0] == 'U') && ( zz->systemid.val[1] == 'D'))
- {
- debug(F101, "zopeno:file originated from OS-9","",zz->lprotect.val[0]);
- if (zz->lprotect.len != 0)
- {
- if (_ss_attr(fp[n]->_fd,(zz->lprotect.val[0]&0x7f)|S_IWRITE) == -1)
- {
- debug(F101, "zopeno:can't set file attr","",errno);
- return(0);
- }
- }
- }
- if (n == ZDFILE) setbuf(fp[n],(char *)NULL); /* Debug file unbuffered */
- return(1);
- }
-
- /* Z C L O S E -- Close the given file. */
- /* Returns 0 if arg out of range, 1 if successful, -1 if close failed. */
-
- zclose(n) int n; {
- int x, x2;
- if (chkfn(n) < 1) return(0); /* Check range of n */
-
- if ((n == ZOFILE) && (zoutcnt > 0)) /* (PWP) output leftovers */
- x2 = zoutdump();
- else
- x2 = 0;
-
- x = 0; /* Initialize return code */
- if (fp[ZSYSFN]) { /* If file is really pipe */
- x = zclosf(n); /* do it specially */
- } else {
- if ((fp[n] != stdout) && (fp[n] != stdin)) x = fclose(fp[n]);
- fp[n] = NULL;
- }
- if (x == EOF) /* if we got a close error */
- return (-1);
- else if (x2 < 0) /* or an error flushing the last buffer */
- return (-1); /* then return an error */
- else
- return (1);
- }
-
- /* Z C H I N -- Get a character from the input file. */
-
- /* Returns -1 if EOF, 0 otherwise with character returned in argument */
-
- zchin(n,c) int n; int *c; {
- int a;
-
- /* (PWP) Just in case this gets called when it shoudn't */
- if (n == ZIFILE)
- return (zminchar());
-
- /* if (chkfn(n) < 1) return(-1); */
- a = getc(fp[n]);
- if (a == EOF) return(-1);
- *c = a & 0377;
- return(0);
- }
-
- /* Z I N F I L L -- Get a character from the input file.
- * (PWP) (re)fill the buffered input buffer with data. All file input
- * should go through this routine, usually by calling the zminchar()
- * macro (in ckcker.h).
- */
-
- zinfill() {
- zincnt = fread((char *)zinbuffer, sizeof (char), INBUFSIZE, fp[ZIFILE]);
- if (zincnt == 0) return (-1); /* end of file */
- zinptr = zinbuffer; /* set pointer to beginning, (== &zinbuffer[0]) */
- zincnt--; /* one less char in buffer */
- return((int)(*zinptr++) & 0377); /* because we return the first */
- }
-
- /* Z S O U T -- Write a string to the given file, buffered. */
-
- zsout(n,s) int n; char *s; {
- if (chkfn(n) < 1) return(-1);
- fputs(s,fp[n]);
- return(0);
- }
-
- /* Z S O U T L -- Write string to file, with line terminator, buffered */
-
- zsoutl(n,s) int n; char *s; {
- /* if (chkfn(n) < 1) return(-1); */
- fputs(s,fp[n]);
- fputs("\n",fp[n]);
- return(0);
- }
-
- /* Z S O U T X -- Write x characters to file, unbuffered. */
-
- zsoutx(n,s,x) int n, x; char *s; {
- /* if (chkfn(n) < 1) return(-1); */
- return(write(fileno(fp[n]),s,(unsigned int)x));
- }
-
-
- /* Z C H O U T -- Add a character to the given file. */
-
- /* Should return 0 or greater on success, -1 on failure (e.g. disk full) */
-
- int
- #ifdef CK_ANSIC
- zchout(register int n, char c)
- #else
- zchout(n,c) register int n; char c;
- #endif /* CK_ANSIC */
- /* zchout */ {
- /* if (chkfn(n) < 1) return(-1); */
- if (n == ZSFILE)
- return(write(fileno(fp[n]),&c,1));/*Use unbuffered for session log*/
- else { /* Buffered for everything else */
- if (putc(c,fp[n]) == EOF) /* If true, maybe there was an error */
- {
- return(ferror(fp[n])); /* Check to make sure */
- }
- else return(0); /* There was no error. */
- }
- }
-
- /* (PWP) buffered character output routine to speed up file IO */
- zoutdump()
- {
- if (zoutcnt == 0) return (0); /* nothing to output */
- if (zoutcnt < 0) return (-1); /* unexpected */
-
- zoutptr = zoutbuffer; /* Reset buffer pointer in all cases */
- if (fwrite ((char *)zoutbuffer, 1, zoutcnt, fp[ZOFILE]))
- {
- fflush(fp[ZOFILE]);
- zoutcnt = 0; /* reset output buffer */
- zoutptr = zoutbuffer;
- return(0); /* things worked OK */
- }
- zoutcnt = 0; /* reset output buffer */
- return(ferror(fp[ZOFILE])?-1:0); /* Check to make sure */
- }
-
- /* C H K F N -- Internal function to verify file number is ok */
-
- /*
- Returns:
- -1: File number n is out of range
- 0: n is in range, but file is not open
- 1: n in range and file is open
- */
- chkfn(n) int n; {
- switch (n) {
- case ZCTERM:
- case ZSTDIO:
- case ZIFILE:
- case ZOFILE:
- case ZDFILE:
- case ZTFILE:
- case ZPFILE:
- case ZSFILE:
- case ZSYSFN:
- case ZRFILE:
- case ZWFILE: break;
-
- default:
- debug(F101,"chkfn: file number out of range","",n);
- fprintf(stderr,"?File number out of range - %d\n",n);
- return(-1);
- }
- return( (fp[n] == NULL) ? 0 : 1 );
- }
-
- /* Z C H K I -- Check if input file exists and is readable */
-
- /*
- Returns:
- >= 0 if the file can be read (returns the size).
- -1 if file doesn't exist or can't be accessed,
- -2 if file exists but is not readable (e.g. a directory file).
- -3 if file exists but protected against read access.
- */
- long
- zchki(name) char *name; {
- int x;
-
- if (access(name,0) < 0) {
- if(access(name,S_IFDIR)>=0) {
- debug(F111,"zchki skipping:",name,errno);
- return(-2);
- }
- debug(F111,"zchki can't access",name,errno);
- return(-1);
- }
-
- if ((x = access(name,S_IREAD)) < 0) { /* Is the file accessible? */
- debug(F111," access failed:",name,x); /* No */
- return(-3);
- }
- debug(F110," access ok:",name,0);
- if((x = open(name,S_IREAD)) < 0) {
- debug(F111,"zchki can't open:",name,errno);
- return(-2);
- }
- debug(F111,"zchki stat ok:",name,x);
- cur_in_size = _gs_size(x); /* remember size */
- _gs_gfd(x,&cur_in_fd,sizeof(cur_in_fd)); /* remember filedespr. */
- close(x);
- debug(F111," access ok:",name,cur_in_size);
- return( (cur_in_size > -1) ? cur_in_size : 0 );
- }
-
- /* Z C H K O -- Check if output file can be created */
-
- /*
- Returns -1 if write permission for the file would be denied, 0 otherwise.
- */
- zchko(name) char *name; {
- int i, x;
- char s[50], *sp;
-
- if(access(name,S_IFDIR)>=0) return -1; /* it's a directory */
- sp = s; /* Make a copy, get length */
- x = 0;
- while ((*sp++ = *name++) != '\0')
- x++;
- if (x == 0) return(-1); /* If no filename, fail. */
-
- debug(F101," length","",x);
- for (i = x; i > 0; i--) { /* Strip filename. */
- if(!isalnum(s[i-1])) {
- switch(s[i-1]) {
- case '.':
- case '$':
- case '_': continue;
- case '/': break;
- default: return -1; /* bad character */
- }
- break;
- }
- }
- debug(F101," i","",i);
- if (i == 0) /* If no path, use current directory */
- strcpy(s,".");
- else { /* Otherwise, use given one. */
- if(i==x) return -1; /* no filename! */
- s[--i] = '\0';
- }
- x = access(s,S_IFDIR|S_IWRITE); /* Check access of path. */
- if (x < 0) {
- fprintf(stderr,"access failed %s errno:%d\n",s,errno);
- debug(F111,"zchko access failed:",s,errno);
- return(-1);
- } else {
- debug(F111,"zchko access ok:",s,x);
- return(0);
- }
- }
-
- /* Z C H K S P A -- Check if there is enough space to store the file */
-
- /*
- Call with file specification f, size n in bytes.
- Returns -1 on error, 0 if not enough space, 1 if enough space.
- */
- zchkspa(f,n) char *f; long n; { /* Just dummy for now. */
- return(1); /* Always say OK. */
- }
-
-
- /* Z D E L E T -- Delete the named file. */
-
- zdelet(name) char *name; {
- return(unlink(name));
- }
-
-
- /* Z R T O L -- Convert remote filename into local form */
-
- /* For OS9, this means changing uppercase letters to lowercase
- and making shure only a-z,A-Z,0-9,$,_,. are used */
- VOID
- zrtol(name,name2) char *name, *name2; {
- for ( ; *name != '\0'; name++) {
- if (isupper(*name))
- *name2++ = tolower(*name);
- else if (islower(*name) || isdigit(*name)
- || *name == '$' || *name == '.' || *name == '_')
- *name2++ = *name;
- else
- *name2++ = '_'; /* otherwise use '_' */
- }
- *name2 = '\0';
- debug(F110,"zrtol:",name2,0);
- }
-
-
- /* Z L T O R -- Local TO Remote */
-
- /* Convert filename from local format to common (remote) form. */
- VOID
- zltor(name,name2) char *name, *name2; {
- char work[100], *cp, *pp;
- int dc = 0;
-
- debug(F110,"zltor",name,0);
- pp = work;
- for (cp = name; *cp != '\0'; cp++) { /* strip path name */
- if (*cp == '/') {
- dc = 0;
- pp = work;
- }
- else if (islower(*cp)) *pp++ = toupper(*cp); /* Uppercase letters */
- else if (*cp == '$') *pp++ = 'X'; /* Change '$' to 'X' */
- else if ((*cp == '.') && (++dc > 1)) *pp++ = 'X'; /* & extra dots */
- else *pp++ = *cp;
- }
- *pp = '\0'; /* Tie it off. */
- cp = name2; /* If nothing before dot, */
- if (*work == '.') *cp++ = 'X'; /* insert 'X' */
- strcpy(cp,work);
- debug(F110," name2",name2,0);
- }
-
-
- /* Z C H D I R -- Change directory */
-
- zchdir(dirnam) char *dirnam; {
- char *hd;
- if (*dirnam == '\0') hd = getenv("HOME");
- else hd = dirnam;
- return((chdir(hd) == 0) ? 1 : 0);
- }
-
-
- /* Z H O M E -- Return pointer to user's home directory */
-
- char *
- zhome() {
- return(getenv("HOME"));
- }
-
- /* Z X C M D -- Run a system command so its output can be read like a file */
-
- zxcmd(filnum,comand) int filnum;char *comand; {
- FILE *pipeopen(),*filedesc;
-
- if (chkfn(filnum) < 0) return(-1); /* Need a valid kermit file number */
- if (filnum == ZSTDIO || filnum == ZCTERM) return(0);
-
- if (filnum == ZIFILE || filnum == ZRFILE) /* kermit wants to read */
- {
- debug(F111," zxcmd read:",comand,filnum);
- if ((filedesc = pipeopen(comand,"r")) != (FILE *)NULL)
- {
- fp[filnum] = filedesc;
- fp[ZSYSFN] = fp[filnum]; /* Remember. */
- zincnt = 0;
- zinptr = zinbuffer;
- }
- else
- return(0);
- }
- else
- {
- debug(F111," zxcmd write:",comand,filnum);
- if ((filedesc = pipeopen(comand,"w")) != (FILE *)NULL)
- {
- fp[filnum] = filedesc;
- fp[ZSYSFN] = fp[filnum]; /* Remember. */
- zoutcnt = 0;
- zoutptr = zoutbuffer;
- }
- else
- return(0);
- }
- return(1); /* return success if we ever get here */
- }
-
- /* KILL_TREE recursively kill all processes of a forked tree */
- static void kill_tree(root) unsigned int root;
- {
- struct {
- unsigned short
- _id, /* process id */
- _pid, /* parent's id */
- _sid, /* sibling's id */
- _cid; /* child's id */
- } prdesc; /* NOT whole process descriptor! too much stack needed */
- unsigned int child;
-
- if(_get_process_desc(root,sizeof(prdesc),&prdesc)==(int)-1) return;
- if ((child = prdesc._cid) != 0) kill_tree(child); /* kill child's tree */
- if ((child = prdesc._sid) != 0) kill_tree(child); /* kill siblings tree */
- kill(root,SIGKILL);
- }
-
- /* Z C L O S F - kill the child(action may have aborted and close the pipe.*/
-
- zclosf(filnum) int filnum;{
- int wstat;
- debug(F101," zclosf filnum:","",filnum);
- fclose(fp[filnum]);
- fp[filnum] = fp[ZSYSFN] = NULL;
- if (pipe_pid == 0) return(-1);
- kill_tree(pipe_pid); /*kill all lower processes in case things have
- been aborted */
- debug(F101," zclosf killed:","",pipe_pid);
- while ((wstat = wait((unsigned int *)0)) != pipe_pid && wstat != -1) ;
- pipe_pid = 0;
- return(1);
- }
-
- /* Z X P A N D -- Expand a wildcard string into an array of strings */
- /*
- Returns the number of files that match fn1, with data structures set up
- so that first file (if any) will be returned by the next znext() call.
- */
- zxpand(fn) char *fn; {
- fcount = fgen(fn,mtchs,MAXWLD); /* Look up the file. */
- if (fcount > 0) {
- mtchptr = mtchs; /* Save pointer for next. */
- }
- debug(F111,"zxpand",mtchs[0],fcount);
- return(fcount);
- }
-
-
- /* Z N E X T -- Get name of next file from list created by zxpand(). */
- /*
- Returns >0 if there's another file,with its name copied into the arg string
- or 0 if no more files in list.
- */
- znext(fn) char *fn; {
- if (fcount-- > 0) strcpy(fn,*mtchptr++);
- else *fn = '\0';
- debug(F111,"znext",fn,fcount+1);
- return(fcount+1);
- }
-
-
- /* Z N E W N -- Make a new name for the given file */
- VOID
- znewn(fn,s) char *fn, **s; {
- static char buf[256];
- char *bp, *xp;
- int len = 0, n = 0, d = 0, t, i, power = 1;
- #ifdef MAXNAMLEN
- int max = MAXNAMLEN;
- #else
- int max = 14;
- #endif
- bp = buf;
- while (*fn) { /* Copy name into buf */
- *bp++ = *fn++;
- len++;
- }
- if (len > max-2) { /* Don't let it get too long */
- bp = buf + max-2;
- len = max - 2;
- }
-
- for (i = 1; i < 4; i++) { /* Try up to 999 times */
- power *= 10;
- *bp++ = '*'; /* Put a star on the end */
- *bp-- = '\0';
-
- n = zxpand(buf); /* Expand the resulting wild name */
-
- while (n-- > 0) { /* Find any existing name_d files */
- xp = *mtchptr++;
- xp += len;
- if (*xp == '_') {
- t = atoi(xp+1);
- if (t > d) d = t; /* Get maximum d */
- }
- }
- if (d < power-1) {
- sprintf(bp,"_%d",d+1); /* Make name_(d+1) */
- *s = buf;
- return;
- }
- bp--; len--;
- }
- /* If we ever get here, we'll overwrite the xxx~100 file... */
- }
-
- /* Z S A T T R */
- /*
- Fills in a Kermit file attribute structure for the file which is to be sent.
- Returns 0 on success with the structure filled in, or -1 on failure.
- If any string member is null, then it should be ignored.
- If any numeric member is -1, then it should be ignored.
- */
- zsattr(xx) struct zattr *xx; {
- int k;
- static char protection[2];
- static char * get_gmtime();
-
- k = cur_in_size % 1024L; /* File length in K */
- if (k != 0L) k = 1L;
- xx->lengthk = (cur_in_size / 1024L) + k;
- /* if ((cur_in_fd.fd_att & S_IEXEC) || (cur_in_fd.fd_att & S_IOEXEC))
- {
- xx->type.len = 1;
- xx->type.val = "B";
- }
- else
- {
- xx->type.len = 0;
- xx->type.val = "";
- }
- */ xx->type.len = 0; /* better let the user decide */
- xx->type.val = "";
- xx->date.val = get_gmtime(&cur_in_fd); /* get UCT time, if possible */
- xx->date.len = strlen(xx->date.val);
- debug(F111,"zsattr date",xx->date.val,xx->date.len);
- xx->creator.len = 0; /* File creator */
- xx->creator.val = "";
- xx->account.len = 0; /* File account */
- xx->account.val = "";
- xx->area.len = 0; /* File area */
- xx->area.val = "";
- xx->passwd.len = 0; /* Area password */
- xx->passwd.val = "";
- xx->blksize = -1L; /* File blocksize */
- xx->access.len = 0; /* File access */
- xx->access.val = "";
- xx->encoding.len = 0; /* Transfer syntax */
- xx->encoding.val = 0;
- xx->disp.len = 0; /* Disposition upon arrival */
- xx->disp.val = "";
-
- protection[0] = cur_in_fd.fd_att & 0x7f;
- protection[1] = 0;
- xx->lprotect.val = protection;
- xx->lprotect.len = 1;
- debug(F101,"zsattr lprotect","",xx->lprotect.val[0]);
-
- xx->gprotect.len = 0; /* Generic protection */
- xx->gprotect.val = "";
- xx->systemid.len = 2; /* System ID */
- xx->systemid.val = "UD";
- xx->recfm.len = 0; /* Record format */
- xx->recfm.val = "";
- xx->sysparam.len = 0; /* System-dependent parameters */
- xx->sysparam.val = "";
- debug(F101,"zsattr size","",cur_in_size);
- xx->length = cur_in_size; /* Length */
- return(0);
- }
-
- zmail(p,f) char *p; char *f; {
- /* Send file f as mail to address p; no mail on OS-9 */
- return(-1);
- }
-
- zprint(p,f) char *p; char *f; {
- /* Print file f with options p; no unique print device on OS-9 */
- return(-1);
- }
-
- /* Directory Functions for Unix, written by Jeff Damens, CUCCA, 1984. */
- /*
- * The path structure is used to represent the name to match.
- * Each slash-separated segment of the name is kept in one
- * such structure, and they are linked together, to make
- * traversing the name easier.
- */
-
- struct path {
- char npart[MAXNAMLEN]; /* name part of path segment */
- struct path *fwd; /* forward ptr */
- };
-
- #define SSPACE 2000 /* size of string-generating buffer */
- static char sspace[SSPACE]; /* buffer to generate names in */
- static char *freeptr,**resptr; /* copies of caller's arguments */
- static int remlen; /* remaining length in caller's array*/
- static int numfnd; /* number of matches found */
-
- /*
- * splitpath:
- * takes a string and splits the slash-separated portions into
- * a list of path structures. Returns the head of the list. The
- * structures are allocated by malloc, so they must be freed.
- * Splitpath is used internally by the filename generator.
- *
- * Input: A string.
- * Returns: A linked list of the slash-separated segments of the input.
- */
-
- struct path *
- splitpath(p)
- char *p;
- {
- struct path *head,*cur,*prv;
- int i;
- head = prv = NULL;
- if (*p == '/') p++; /* skip leading slash */
- while (*p != '\0') {
- cur = (struct path *) malloc(sizeof (struct path));
- debug(F101,"splitpath malloc","",(int)cur);
- if (cur == NULL) fatal("malloc fails in splitpath()");
- cur -> fwd = NULL;
- if (head == NULL) head = cur;
- else prv -> fwd = cur; /* link into chain */
- prv = cur;
- for (i=0; i < MAXNAMLEN && *p != '/' && *p != '\0'; i++)
- cur -> npart[i] = *p++;
- cur -> npart[i] = '\0'; /* end this segment */
- if (i >= MAXNAMLEN) while (*p != '/' && *p != '\0') p++;
- if (*p == '/') p++;
- }
- return(head);
- }
-
- /*
- * fgen:
- * This is the actual name generator. It is passed a string,
- * possibly containing wildcards, and an array of character pointers.
- * It finds all the matching filenames and stores them into the array.
- * The returned strings are allocated from a static buffer local to
- * this module (so the caller doesn't have to worry about deallocating
- * them); this means that successive calls to fgen will wipe out
- * the results of previous calls. This isn't a problem here
- * because we process one wildcard string at a time.
- *
- * Input: a wildcard string, an array to write names to, the
- * length of the array.
- * Returns: the number of matches. The array is filled with filenames
- * that matched the pattern. If there wasn't enough room in the
- * array, -1 is returned.
- * By: Jeff Damens, CUCCA, 1984.
- */
-
- fgen(pat,resarry,len)
- char *pat,*resarry[];
- int len;
- {
- VOID traverse();
- struct path *head;
- char scratch[100+MAXNAMLEN],*sptr;
- head = splitpath(pat);
- if (*pat == '/') {
- scratch[0] = '/';
- sptr = scratch+1;
- *sptr = '\0';
- } else {
- strcpy(scratch,"./");
- sptr = scratch+2;
- } /* init buffer correctly */
- numfnd = 0; /* none found yet */
- freeptr = sspace; /* this is where matches are copied */
- resptr = resarry; /* static copies of these so*/
- remlen = len; /* recursive calls can alter them */
- traverse(head,scratch,sptr); /* go walk the directory tree */
- while (head != NULL) {
- struct path *next = head -> fwd;
- free((char *)head);
- head = next;
- }
- return(numfnd); /* and return the number of matches */
- }
-
- /* traverse:
- * Walks the directory tree looking for matches to its arguments.
- * The algorithm is, briefly:
- * If the current pattern segment contains no wildcards, that
- * segment is added to what we already have. If the name so far
- * exists, we call ourselves recursively with the next segment
- * in the pattern string; otherwise, we just return.
- *
- * If the current pattern segment contains wildcards, we open the name
- * we've accumulated so far (assuming it is really a directory), then read
- * each filename in it, and, if it matches the wildcard pattern segment,add
- * that filename to what we have so far and call ourselves recursively on
- * the next segment.
- *
- * Finally, when no more pattern segments remain, we add what's accumulated
- * so far to the result array and increment the number of matches.
- *
- * Input: a pattern path list (as generated by splitpath), a string
- * pointer that points to what we've traversed so far (this
- * can be initialized to "/" to start the search at the root
- * directory, or to "./" to start the search at the current
- * directory), and a string pointer to the end of the string
- * in the previous argument.
- * Returns: nothing.
- */
- VOID
- traverse(pl,sofar,endcur)
- struct path *pl;
- register char *sofar,*endcur;
- {
- DIR *fd, *opendir();
- VOID addresult();
- struct direct *dirbuf;
- debug(F110,"traverse ",sofar,0);
- if (pl == NULL) {
- *--endcur = '\0'; /* end string, overwrite trailing / */
- addresult(sofar);
- return;
- }
- if (!iswild(pl -> npart)) {
- strcpy(endcur,pl -> npart);
- endcur += strlen(endcur);
- if (access(sofar,S_IFDIR) == 0) { /* if current piece exists & dir */
- *endcur++ = '/'; /* add slash to end */
- *endcur = '\0'; /* and end the string */
- traverse(pl -> fwd,sofar,endcur);
- } else if(access(sofar,0) == 0 && pl->fwd==NULL) {
- addresult(sofar);
- }
- return;
- }
-
- /* segment contains wildcards, have to search directory */
- *--endcur = '\0'; /* end current string */
- if (access(sofar,S_IFDIR) < 0) {
- debug(F111,"traverse can't access directory",sofar,errno);
- return; /* doesn't exist, forget it */
- }
- if ((fd = opendir(sofar)) == NULL) {
- debug(F111,"traverse can't open directory",sofar,errno);
- return; /* can't open, forget it */
- }
- *endcur++ = '/';
- while (dirbuf = readdir(fd)) {
- if (dirbuf->d_addr != 0) {
- strncpy(endcur,dirbuf->d_name,MAXNAMLEN); /* Get a null
- terminated copy!!! */
- if(match(pl -> npart,endcur)) {
- char *eos;
- eos = endcur + strlen(endcur);
- *eos++ = '/'; /* end this segment */
- *eos = '\0';
- traverse(pl -> fwd,sofar,eos);
- }
- }
- }
- closedir(fd);
- }
-
- /*
- * addresult:
- * Adds a result string to the result array. Increments the number
- * of matches found, copies the found string into our string
- * buffer, and puts a pointer to the buffer into the caller's result
- * array. Our free buffer pointer is updated. If there is no
- * more room in the caller's array, the number of matches is set to -1.
- * Input: a result string.
- * Returns: nothing.
- */
-
- VOID
- addresult(str)
- register char *str;
- {
- register int l;
- if (strncmp(str,"./",2) == 0) str += 2;
- if (--remlen < 0) {
- numfnd = -1;
- return;
- }
- l = strlen(str) + 1; /* size this will take up */
- if ((freeptr + l) > &sspace[SSPACE]) {
- numfnd = -1; /* do not record if not enough space */
- return;
- }
- strcpy(freeptr,str);
- *resptr++ = freeptr;
- freeptr += l;
- numfnd++;
- }
-
- iswild(str)
- register char *str;
- {
- register char c;
- while ((c = *str++) != '\0')
- if (c == '*' || c == '?') return(1);
- return(0);
- }
-
- /*
- * match:
- * pattern matcher. Takes a string and a pattern possibly containing
- * the wildcard characters '*' and '?'. Returns true if the pattern
- * matches the string, false otherwise.
- * Input: a string and a wildcard pattern.
- * Returns: 1 if match, 0 if no match.
- */
-
- match(pattern,string) char *pattern,*string; {
- int i;
- i = _cmpnam(string,pattern,strlen(pattern))==0;
- debug(F111,"Match ",string,i);
- return i;
- }
-
- /* emulate unix perror function */
-
- perror(string)
- char *string;
- {
- extern int errno;
- fprintf(stderr,"%s ERRNO: %d\n",string,errno);
- }
-
- #ifdef DTILDE
- char *
- tilde_expand(dirname)
- register char *dirname;
- {
- static char *home = NULL;
- static char temp[MAXNAMLEN];
-
- debug(F111,"tilde_expand dirname", dirname, dirname[0]);
- if(*dirname++ != '~' || (*dirname != '\0' && *dirname != '/'))
- return --dirname;
- if(home == NULL && (home = getenv("HOME")) == NULL) return --dirname;
- if(*dirname == '\0') return home;
- strcpy(temp, home);
- strcat(temp, dirname);
- return temp;
- }
- #endif
-
- /* Z S T I M E -- Set creation date for incoming file */
- /*
- Call with:
- f = pointer to name of existing file.
- yy = pointer to a Kermit file attribute structure in which yy->date.val
- is a date of the form [yy]yymmdd[ hh:mm[:ss]] e.g. 19900208 13:00:00.
- x = is a function code: 0 means to set the file's creation date as given.
- 1 means compare the given date with the file creation date.
- Returns:
- -1 on any kind of error.
- 0 if x is 0 and the file date was set successfully.
- 0 if x is 1 and date from attribute structure > file creation date.
- 1 if x is 1 and date from attribute structure <= file creation date.
- */
-
- zstime(f,yy,x) char *f; register struct zattr *yy; int x;
- {
- extern int errno;
- int r = -1; /* return code */
- int path;
- register char *point;
- register char save;
- char year,month,day,hour,minute,second;
- struct fildes buffer;
- unsigned char long_year=0,hour_min=0,err=0;
- time_t mktime(),file_date;
- static VOID convert_to_local_time();
- struct tm tp;
- debug(F110,"zstime",f,0);
-
- switch (yy->date.len)
- {
- case 0:
- err = 1;
- break;
- case 6: /* yymmdd */
- break;
- case 8: /* yyyymmdd */
- long_year = 1;
- break;
- case 12: /* yymmdd hh:mm */
- hour_min = 1;
- break;
- case 14: /* yyyymmdd hh:mm */
- long_year = 1;
- hour_min = 1;
- break;
- case 15: /* yymmdd hh:mm:ss */
- hour_min = 1;
- break;
- case 17: /* yyyymmdd hh:mm::ss */
- long_year = 1;
- hour_min = 1;
- break;
- default:
- err = 1;
- break;
- }
- if (err)
- {
- debug(F111,"Bad creation date ",yy->date.val,yy->date.len);
- return(-1);
- }
-
- point = yy->date.val;
- if (long_year)
- {
- save = *(point+4);
- *(point+4) = '\0';
- year = atoi(point);
- *(point+4) = save;
- point += 4;
- year -= 1900; /* OS-9 only has year since 1900 */
- }
- else
- {
- save = *(point+2);
- *(point+2) = '\0';
- year = atoi(point);
- point += 2; /* don't add 1900: OS-9 only has year since 1900 anyway */
- }
-
- save = *(point+2);
- *(point+2) = '\0';
- month = atoi(point);
- *(point+2) = save;
-
- point += 2;
- save = *(point+2);
- *(point+2) = '\0';
- day = atoi(point);
- *(point+2) = save;
-
- if (hour_min)
- {
- point += 3; /* skip the blank */
- save = *(point+2);
- *(point+2) = '\0';
- hour = atoi(point);
- *(point+2) = save;
-
- point += 3; /* skip the : */
- save = *(point+2);
- *(point+2) = '\0';
- minute = atoi(point);
- *(point+2) = save;
-
- second = 0; /* no OS-9 seconds */
- }
- else /* no hours and minutes given */
- {
- hour = minute = second = 0;
- }
- err = 0;
- if (year >99) err = 1;
- if ((month >12) || (month < 1)) err = 1;
- if ((day >31) || (day < 1)) err = 1;
- if (hour >23) err = 1;
- if (minute >59) err = 1;
-
- if (err)
- {
- debug(F111,"Bad creation date ",yy->date.val,yy->date.len);
- return(-1);
- }
-
- convert_to_local_time(&year,&month,&day,&hour,&minute,&second);
-
- if ((path = open(f,0)) == -1) /* mode 0 is sufficient for _gs_gfd */
- {
- debug(F110,"Can't open file to get fdesc:",f,0);
- return(r);
- }
- if (_gs_gfd(path,&buffer,sizeof(buffer)) == -1)
- {
- debug(F111,"Can't get descriptor for file:",f,errno);
- close(path);
- return(r);
- }
- close(path);
- switch (x) /* Execute desired function */
- {
- case 0: /* Set the creation and modification date of the file */
- buffer.fd_date[0] = year;
- buffer.fd_date[1] = month;
- buffer.fd_date[2] = day;
- buffer.fd_date[3] = hour;
- buffer.fd_date[4] = minute;
- buffer.fd_dcr[0] = year;
- buffer.fd_dcr[1] = month;
- buffer.fd_dcr[2] = day;
- if ((path = open(f,S_IWRITE)) == -1) /* _ss_pfd needs writing */
- {
- debug(F110,"Can't open file for write:",f,0);
- return(r);
- }
- if (_ss_pfd(path,&buffer) == -1)
- {
- debug(F111,"Can't update descriptor for file:",f,errno);
- }
- else
- {
- debug(F110,"Creat. and mod. time is set for file: ",f,0);
- r = 0;
- }
- close(path);
- break;
- case 1: /* Compare the dates */
- tp.tm_sec = 0;
- tp.tm_min = buffer.fd_date[4];
- tp.tm_hour = buffer.fd_date[3];
- tp.tm_mday = buffer.fd_date[2];
- tp.tm_mon = buffer.fd_date[1]-1;
- tp.tm_year = buffer.fd_date[0];
-
- file_date = mktime(&tp);
-
- tp.tm_min = minute;
- tp.tm_hour = hour;
- tp.tm_mday = day;
- tp.tm_mon = month-1;
- tp.tm_year = year;
-
- if (mktime(&tp) > file_date) r=0;
- else r=1;
- break;
- default: /* Error */
- break;
- }
- close(path);
- return(r);
- }
-
- /* Z R E N A M E -- Rename a file */
-
- /* Call with old and new names */
- /* Returns 0 on success, -1 on failure. */
-
- zrename(old,new) register char *old, *new;
- {
- char buffer[256];
- sprintf(buffer,"rename %s %s",old,new);
- if (zsyscmd(buffer) != 0)
- {
- debug(F111,"Can't rename:",old,errno);
- return(-1);
- }
- return(0);
- }
-
- /*
- Functions for executing system commands.
- zsyscmd() executes the system command in the normal, default way for
- the system. In UNIX, it does what system() does. Thus, its results
- are always predictable.
- zshcmd() executes the command using the user's preferred shell.
- */
- zsyscmd(s) char *s;
- {
- unsigned int status;
- extern int os9forkc();
- extern char **environ;
- char *(argblk[3]);
- int pid,wstat;
- debug(F110,"zsyscmd:try:",s,0);
- /* chaining (shell ex command) would save a process but */
- argblk[2] = 0; /* f$chain does not use PATH */
- argblk[1] = s;
- argblk[0] = "shell";
- if ((pid = os9exec(os9forkc,argblk[0],argblk,environ,0,0,3)) > 0)
- {
- while ((wstat = wait(&status)) != pid && wstat != -1) ;
- if (status != 0)
- {
- debug(F111,"zsyscmd:can't execute:",s,status);
- /* return(-1); */
- }
- }
- else
- {
- debug(F111,"zsyscmd:can't fork:",s,errno);
- /* return(-1); */
- }
- debug(F110,"zsyscmd: success:",s,0);
- return(0);
- }
-
- zshcmd(s) register char *s;
- {
- unsigned int status;
- extern int os9forkc();
- extern char **environ;
- char *(argblk[3]);
- int pid,wstat;
- debug(F110,"zshcmd:try:",s,0);
- /* chaining (shell ex command) would save a process but */
- argblk[2] = 0; /* f$chain does not use PATH */
- argblk[1] = s;
- argblk[0] = getenv("SHELL");
- if (argblk[0] == (char *)0) argblk[0] = "shell";
- if ((pid = os9exec(os9forkc,argblk[0],argblk,environ,0,0,3)) > 0)
- {
- while ((wstat = wait(&status)) != pid && wstat != -1) ;
- if (status != 0)
- {
- debug(F111,"zshcmd:can't execute:",s,status);
- /* return(-1); */
- }
- }
- else
- {
- debug(F111,"zshcmd:can't fork:",s,errno);
- /* return(-1); */
- }
- return(0);
- }
-
- /* Z S T R I P -- Strip device & directory name from file specification */
-
- /* Strip pathname from filename "name", return pointer to result in name2 */
-
- char work[100]; /* buffer for use by zstrip and zltor */
-
- VOID
- zstrip(name,name2) char *name, **name2; {
- char *cp, *pp;
- debug(F110,"zstrip before",name,0);
- pp = work;
- #ifdef DTILDE
- if (*name == '~') name++;
- #endif
- for (cp = name; *cp != '\0'; cp++) {
- if (*cp == '/')
- pp = work;
- else
- *pp++ = *cp;
- }
- *pp = '\0'; /* Terminate the string */
- *name2 = work;
- debug(F110,"zstrip after",*name2,0);
- }
-
- /* Z S I N L -- Read a line from a file */
-
- /*
- Writes the line into the address provided by the caller.
- n is the Kermit "channel number".
- Writing terminates when newline is encountered, newline is not copied.
- Writing also terminates upon EOF or if length x is exhausted.
- Returns 0 on success, -1 on EOF or error.
- */
- zsinl(n,s,x) int n, x; char *s; {
- int a, z = 0;
-
- if (chkfn(n) < 1) { /* Make sure file is open */
- return(-1);
- }
- a = -1;
- while (x--) {
- if (zchin(n,&a) < 0) { /* Read a character from the file */
- z = -1;
- break;
- }
- if ( a == (char) NLCHAR) break; /* Single-character line terminator */
- *s = a;
- s++;
- }
- *s = '\0';
- return(z);
- }
-
- static char
- *get_gmtime(file_desc) struct fildes *file_desc;
- /* returns UCT/GMT yyyymmdd hh:mm:00 time out of the file descriptor
- if im possible to get GMT it takes the time from the file descriptor
- without converion */
- {
- static char datbuf[18]; /* must be static !!! */
- struct tm *gmt,tp;
- time_t local_file_date;
- unsigned char we_know_gmt=0;
-
- while(1)
- {
- if (getenv("TZ") == (char *)NULL) /* if TZ not defined send modification
- date literally */
- break;
-
- tp.tm_sec = 0;
- tp.tm_min = file_desc->fd_date[4];
- tp.tm_hour = file_desc->fd_date[3];
- tp.tm_mday = file_desc->fd_date[2];
- tp.tm_mon = file_desc->fd_date[1]-1;
- tp.tm_year = file_desc->fd_date[0];
- local_file_date = mktime(&tp);
-
- if (local_file_date == (time_t)-1) /* take time literally */
- break;
-
- gmt = gmtime(&local_file_date);
-
- if (gmt == (struct tm*)NULL) /* take time literally */
- break;
-
- we_know_gmt = 1;
- break;
- } /* end while (1) */
-
- if (we_know_gmt)
- sprintf(datbuf,"%4d%02d%02d %02d:%02d:%02d",
- 1900L+(unsigned int)gmt->tm_year,
- gmt->tm_mon+1,gmt->tm_mday,gmt->tm_hour,gmt->tm_min,0);
- else
- sprintf(datbuf,"%4d%02d%02d %02d:%02d:%02d",
- 1900L+(unsigned int)file_desc->fd_date[0],
- file_desc->fd_date[1],file_desc->fd_date[2],
- file_desc->fd_date[3],file_desc->fd_date[4],0);
- return(datbuf);
- }
- static VOID
- convert_to_local_time(year,month,day,hour,minute,second)
- char *year,*month,*day,*hour,*minute,*second;
- /* will convert to local time if timezone information is available assuming
- UCT/GMT time as input , otherwise just return.
- year must be since 1900 */
- {
- struct tm *tp;
- time_t cal_date;
- int time,date;
- char *getenv();
-
- if (getenv("TZ") == (char *)NULL) return;
- date = ((1900+*year)<<16)+(*month<<8)+*day;
- time = (*hour<<16)+(*minute<<8)+*second;
- if (_julian(&time,&date) == -1) return;
- cal_date = (date-2440587)*86400+time; /* 2440587 = 1st of Jan 1970 */
-
- tp = localtime(&cal_date);
-
- if (tp == (struct tm*)NULL) return;
-
- *second = tp->tm_sec;
- *minute = tp->tm_min;
- *hour = tp->tm_hour;
- *day = tp->tm_mday;
- *month = tp->tm_mon+1;
- *year = tp->tm_year;
-
- }
- FILE *
- pipeopen(command,access_type) char *command,*access_type;
- {
- extern int os9forkc();
- extern char **environ;
- int duped,dupederr,stdinout;
- FILE *pipe;
- char *argv[3];
-
- if (*access_type=='r') stdinout = 1; /* redirect stdout and stderr*/
- else if (*access_type=='w') stdinout = 0; /* redirect stdin */
- else return((FILE *)NULL);
-
- if((duped = dup(stdinout)) <= 0) return((FILE *)NULL);
- if(stdinout == 1)
- {
- if((dupederr = dup(2)) <= 0)
- {
- close(duped);
- return((FILE *)NULL);
- }
- }
- if((pipe = fopen("/pipe", "r+")) == NULL)
- {
- close(duped);
- if(stdinout == 1) close(dupederr);
- return((FILE *)NULL);
- }
- close(stdinout);
- dup(fileno(pipe));
- if (stdinout == 1) /* also dupe stderr */
- {
- close(2);
- dup(fileno(pipe));
- }
- argv[0] = "shell";
- argv[1] = command;
- argv[2] = (char *)NULL;
- if((pipe_pid = os9exec(os9forkc,argv[0],argv,environ,0,0,3)) < 0)
- {
- pipe_pid = 0;
- fclose(pipe);
-
- close(stdinout);
- dup(duped); /* restore old stdinout */
- close(duped);
- if(stdinout == 1) /* also restore old sterr */
- {
- close(2);
- dup(dupederr);
- close(dupederr);
- }
- return (FILE *)NULL;
- }
- debug(F101," pipeopen success id:","",pipe_pid);
- close(stdinout);
- dup(duped);
- close(duped);
- if(stdinout == 1)
- {
- close(2);
- dup(dupederr);
- close(dupederr);
- }
- return(pipe);
- }
-